/*
 * 
 */
package com.yuanmei.stockeyes.charts;

import android.content.Context;
import android.graphics.Color;
import android.graphics.PointF;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.View;
import android.view.View.OnTouchListener;

import com.tictactec.ta.lib.Core;
import com.tictactec.ta.lib.MInteger;
import com.tictactec.ta.lib.RetCode;
import com.yuanmei.stockeyes.R;
import com.yuanmei.stockeyes.artifacts.Extensions;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import cn.limc.androidcharts.entity.DateValueEntity;
import cn.limc.androidcharts.entity.LineEntity;
import cn.limc.androidcharts.event.IDisplayCursorListener;
import cn.limc.androidcharts.view.SlipMinusLineChart;

//import android.util.Log;

public class TalibRsiChart implements ITalibChart {
    private final Core mTaLibCore = new Core();
    private Context mContext;
    private SlipMinusLineChart mRsiChartView;
    private static final String TAG = TalibRsiChart.class.getName();

    private List<DateValueEntity> mRsiFastDateValueList;
    private List<DateValueEntity> mRsiMediumDateValueList;
    private List<DateValueEntity> mRsiSlowDateValueList;

    private LineEntity<DateValueEntity> mRsiFastLineEntity;
    private LineEntity<DateValueEntity> mRsiMediumLineEntity;
    private LineEntity<DateValueEntity> mRsiSlowLineEntity;
    private int mRsiFastPeriod   = 5;
    private int mRsiMediumPeriod = 10;
    private int mRsiSlowPeriod   = 15;

    private String mRsiFastPeriodName;
    private String mRsiMediumPeriodName;
    private String mRsiSlowPeriodName;

    private int mTaIdxDataSetsBegin;
    private int mTaIdxDataSetsNumber;

    public TalibRsiChart(Context context) {
        mRsiChartView = new SlipMinusLineChart(context);
        TalibChartFactory.commonInitGridChart(mRsiChartView);
        TalibChartFactory.commonInitSlipLineChart(mRsiChartView);

        mContext =  mRsiChartView.getContext();
        mRsiFastPeriodName   = mContext.getString(R.string.param_rsi_fast_period);
        mRsiMediumPeriodName = mContext.getString(R.string.param_rsi_meidum_period);
        mRsiSlowPeriodName   = mContext.getString(R.string.param_rsi_slow_period);
    }

    @Override
    public List<Map<String, Object>> getTaParamsList() {

        List<Map<String, Object>> outParamsList = new ArrayList<Map<String, Object>>();
        Map<String, Object> item = new HashMap<String, Object>();

        item = new HashMap<String, Object>();
        item.put(ITalibChart.ITaParamNameKey,  mRsiFastPeriodName);
        item.put(ITalibChart.ITaParamValueKey, mRsiFastPeriod);
        outParamsList.add(item);

        item = new HashMap<String, Object>();
        item.put(ITalibChart.ITaParamNameKey,  mRsiMediumPeriodName);
        item.put(ITalibChart.ITaParamValueKey, mRsiMediumPeriod);
        outParamsList.add(item);


        item.put(ITalibChart.ITaParamNameKey,  mRsiSlowPeriodName);
        item.put(ITalibChart.ITaParamValueKey, mRsiSlowPeriod);
        outParamsList.add(item);
        return outParamsList;
    }

    @Override
    public void setTaParams(Hashtable<String, Integer> inParamMaps) {
        if (inParamMaps.containsKey(mRsiSlowPeriodName)
                && inParamMaps.containsKey(mRsiFastPeriodName)
                && inParamMaps.containsKey(mRsiMediumPeriodName)
                ) {
            mRsiFastPeriod = inParamMaps.get(mRsiFastPeriodName);
            mRsiMediumPeriod = inParamMaps.get(mRsiMediumPeriodName);
            mRsiSlowPeriod = inParamMaps.get(mRsiSlowPeriodName);
        }
    }

    @Override
    public boolean reloadData(int dataLen,
                              float[] openPrices,
                              float[] highPrices,
                              float[] lowPrices,
                              float[] closePrices,
                              float[] volumes,
                              float[] amounts,
                              int[] dates) {
        MInteger outFastBegIdx    = new MInteger();
        MInteger outFastNBElement = new MInteger();
        double[] outFastRsi       = new double[dataLen];

        RetCode retCode = mTaLibCore.rsi(0, closePrices.length - 1, closePrices, mRsiFastPeriod,
                outFastBegIdx, outFastNBElement, outFastRsi);
        if (retCode != RetCode.Success) {
            Log.e(TAG, "OBV Chart  calc error retCode=" + retCode);
            return false;
        }

        MInteger outMediumBegIdx    = new MInteger();
        MInteger outMediumNBElement = new MInteger();
        double[] outMediumRsi       = new double[dataLen];

        retCode = mTaLibCore.rsi(0, closePrices.length - 1, closePrices, mRsiMediumPeriod,
                outMediumBegIdx, outMediumNBElement, outMediumRsi);
        if (retCode != RetCode.Success) {
            Log.e(TAG, "OBV Chart  calc error retCode=" + retCode);
            return false;
        }

        MInteger outSlowBegIdx    = new MInteger();
        MInteger outSlowNBElement = new MInteger();
        double[] outSlowRsi       = new double[dataLen];

        retCode = mTaLibCore.rsi(0, closePrices.length - 1, closePrices, mRsiSlowPeriod,
                outSlowBegIdx, outSlowNBElement, outSlowRsi);
        if (retCode != RetCode.Success) {
            Log.e(TAG, "OBV Chart  calc error retCode=" + retCode);
            return false;
        }
 
        mRsiFastDateValueList = new ArrayList<>();
        for (int i = 0; i < dataLen; i++) {
            if (i < outFastBegIdx.value) {
                mRsiFastDateValueList.add(new DateValueEntity(
                        (float) (outFastRsi[0]), dates[i]));
            } else {
                int idx = i - outFastBegIdx.value;
                mRsiFastDateValueList.add(new DateValueEntity(
                        (float) (outFastRsi[idx]), dates[i]));
            }
        }
        
        mRsiMediumDateValueList = new ArrayList<>();
        for (int i = 0; i < dataLen; i++) {
            if (i < outMediumBegIdx.value) {
                mRsiMediumDateValueList.add(new DateValueEntity(
                        (float) (outMediumRsi[0]), dates[i]));
            } else {
                int idx = i - outMediumBegIdx.value;
                mRsiMediumDateValueList.add(new DateValueEntity(
                        (float) (outMediumRsi[idx]), dates[i]));
            }
        }

        mRsiSlowDateValueList = new ArrayList<>();
        for (int i = 0; i < dataLen; i++) {
            if (i < outSlowBegIdx.value) {
                mRsiSlowDateValueList.add(new DateValueEntity(
                        (float) (outSlowRsi[0]), dates[i]));
            } else {
                int idx = i - outSlowBegIdx.value;
                mRsiSlowDateValueList.add(new DateValueEntity(
                        (float) (outSlowRsi[idx]), dates[i]));
            }
        }

        List<LineEntity<DateValueEntity>> lines = new ArrayList<LineEntity<DateValueEntity>>();

        mRsiFastLineEntity = new LineEntity<DateValueEntity>();
        mRsiFastLineEntity.setTitle("RSI-F");
        mRsiFastLineEntity.setLineColor(Color.WHITE);
        mRsiFastLineEntity.setLineData(mRsiFastDateValueList);
        lines.add(mRsiFastLineEntity);

        mRsiMediumLineEntity = new LineEntity<DateValueEntity>();
        mRsiMediumLineEntity.setTitle("RSI-F");
        mRsiMediumLineEntity.setLineColor(Color.YELLOW);
        mRsiMediumLineEntity.setLineData(mRsiMediumDateValueList);
        lines.add(mRsiMediumLineEntity);

        mRsiSlowLineEntity = new LineEntity<DateValueEntity>();
        mRsiSlowLineEntity.setTitle("RSI-F");
        mRsiSlowLineEntity.setLineColor(Color.CYAN);
        mRsiSlowLineEntity.setLineData(mRsiSlowDateValueList);
        lines.add(mRsiSlowLineEntity);

        mRsiChartView.setLinesData(lines);

        mTaIdxDataSetsBegin  = Math.max(outFastBegIdx.value,
                Math.max(outMediumBegIdx.value, outSlowBegIdx.value));
        mTaIdxDataSetsNumber = Math.min(outFastNBElement.value,
                Math.min(outMediumNBElement.value, outSlowNBElement.value));
        return true;
    }

    @Override
    public int getTaIndexNumber() {
        return mTaIdxDataSetsNumber;
    }

    @Override
    public String getTaIndexParms() {
        return  mRsiFastPeriod
                + "," + mRsiMediumPeriod
                + "," + mRsiSlowPeriod;
    }

    @Override
    public String getTaIndexShortName() {
        return "RSI";
    }

    @Override
    public Spanned getTaIndexDetail() {
        if (null == mRsiFastDateValueList 
                || null == mRsiMediumDateValueList
                || null == mRsiSlowDateValueList
                ) {
            return new SpannableString("----");
        }
        int index = mRsiChartView.getSelectedIndex();

        DateValueEntity fastEntity = mRsiFastDateValueList.get(index);
        DateValueEntity mediumEntity = mRsiMediumDateValueList.get(index);
        DateValueEntity slowEntity = mRsiSlowDateValueList.get(index);

        String fastText   = String.format(Locale.ENGLISH, "RSI1:%.2f ", fastEntity.getValue());
        String mediumText   = String.format(Locale.ENGLISH, "RSI2:%.2f ", mediumEntity.getValue());
        String slowText  = String.format(Locale.ENGLISH, "RSI3:%.2f ", slowEntity.getValue());
        //String dateText  = String.format(Locale.ENGLISH, "%d ", slowEntity.getDate());

        String    finalString = fastText + mediumText + slowText;
        Spannable sb          = new SpannableString(finalString);

        sb.setSpan(new ForegroundColorSpan(mRsiFastLineEntity.getLineColor()),
                finalString.indexOf(fastText),
                finalString.indexOf(fastText) + fastText.length(),
                Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
        sb.setSpan(new ForegroundColorSpan(mRsiMediumLineEntity.getLineColor()),
                finalString.indexOf(mediumText),
                finalString.indexOf(mediumText) + mediumText.length(),
                Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
        sb.setSpan(new ForegroundColorSpan(mRsiSlowLineEntity.getLineColor()),
                finalString.indexOf(slowText),
                finalString.indexOf(slowText) + slowText.length(),
                Spanned.SPAN_EXCLUSIVE_INCLUSIVE);

//        sb.setSpan(new ForegroundColorSpan(Color.GRAY), finalString.indexOf(dateText),
//                finalString.indexOf(dateText) + dateText.length(),
//                Spanned.SPAN_EXCLUSIVE_INCLUSIVE);

        return (sb);
    }

    @Override
    public int getTaIndexBegin() {
        return mTaIdxDataSetsBegin;
    }

    @Override
    public View getChartView() {
        return mRsiChartView;
    }

    @Override
    public void setDisplayFrom(int from) {
        mRsiChartView.setDisplayFrom(from);
    }

    @Override
    public void setDisplayCrossXOnTouch(boolean displayCrossXOnTouch) {
        mRsiChartView.setDisplayCrossXOnTouch(displayCrossXOnTouch);
    }

    @Override
    public void setDisplayNumber(int number) {
        mRsiChartView.setDisplayNumber(number);
    }

    @Override
    public void setOnTouchListener(OnTouchListener l) {
        mRsiChartView.setOnTouchListener(l);
    }

    @Override
    public void setOnDisplayCursorListener(
            IDisplayCursorListener l) {
        mRsiChartView.setOnDisplayCursorListener(l);
    }

    @Override
    public PointF getTouchPoint() {
        return mRsiChartView.getTouchPoint();
    }

    @Override
    public void setTouchPoint(PointF touchPoint) {
        mRsiChartView.setTouchPoint(touchPoint);
    }

    @Override
    public void postInvalidate() {
        mRsiChartView.postInvalidate();
    }

    @Override
    public float getValidMiddleY() {
        return mRsiChartView.getValidMiddleY();
    }
}
